package com.rfsp.mcp.service;

import java.io.*;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.rfsp.common.util.DateUtil;
import com.rfsp.common.util.FileUtil;
import com.rfsp.common.util.XssUtils;
import com.rfsp.common.cache.DictCache;
import com.rfsp.mcp.enums.McpConst;
import com.rfsp.mcp.pojo.dto.MiPayDTO;
import com.rfsp.mcp.pojo.dto.MiPayLogDTO;
import com.rfsp.mcp.pojo.vo.*;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rfsp.common.base.BaseService;
import com.rfsp.mcp.mapper.MiPayMapper;
import com.rfsp.mcp.pojo.po.MiPayPO;
import com.rfsp.mcp.pojo.sdto.MiPaySDTO;
import com.rfsp.common.pojo.sdto.PageSDTO;
import org.springframework.util.StreamUtils;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;

@Service
public class PayService extends BaseService<MiPayPO> {

    public Logger logger = LoggerFactory.getLogger(PayService.class);

    private static final String PAY_EXCEL_TEMLLATE_PATH = "excelTemplates/hos/paylog";

    private static Map<String,String> paymentNatureMap = new ConcurrentHashMap<>();

    @Value("${mcp.file-temp-path-pay}")
    private String payExcelPath;

    @Autowired
    MiPayMapper miPayMapper;

    @PostConstruct
    public void init() {
        paymentNatureMap.put("1", "按月拨付金额");
    }

	public PageInfo<MiPayVO> get(MiPaySDTO sdto, PageSDTO pageSdto){
        if(pageSdto!=null){
            PageHelper.startPage(pageSdto.getPageNum(), pageSdto.getPageSize());
        }
        
        List<MiPayVO> voList = miPayMapper.get(sdto);
        
        PageInfo<MiPayVO> page = new PageInfo(voList);
        return page;
    }

    public PageInfo<MiPayVO> getList(MiPaySDTO sdto, PageSDTO pageSdto){
        if(pageSdto!=null){
            PageHelper.startPage(pageSdto.getPageNum(), pageSdto.getPageSize());
        }

        List<MiPayVO> voList = miPayMapper.getList(sdto);

        PageInfo<MiPayVO> page = new PageInfo(voList);
        return page;
    }

    public List<MiPayVO> get(MiPaySDTO sdto){
        List<MiPayVO> voList = miPayMapper.get(sdto);
        return voList;
    }

    @Autowired
    DictCache dictCache;

	public void combo(MiPayVO vo){
        String name=dictCache.DictMap.get("YLLB").get(vo.getPayYllb());
		vo.setPayYllbName(name);
        name=dictCache.DictMap.get("XZLX").get(vo.getPayXzlx());
        vo.setPayXzlxName(name);
        vo.setPaymentNature(StringUtils.isNotBlank(vo.getPaymentNature()) ? paymentNatureMap.get(vo.getPaymentNature()) : "");
        //SimpleDateFormat df=new SimpleDateFormat("yyyy-MM");

        if (vo.getApplyAmount() != null) {
            vo.setApplyAmount(vo.getApplyAmount().setScale(2, RoundingMode.HALF_UP));
        }
        if (vo.getTotalAmount() != null) {
            vo.setTotalAmount(vo.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
        }
        if (vo.getFundPayment() != null) {
            vo.setFundPayment(vo.getFundPayment().setScale(2, RoundingMode.HALF_UP));
        }
        if (vo.getAccountPayment() != null) {
            vo.setAccountPayment(vo.getAccountPayment().setScale(2, RoundingMode.HALF_UP));
        }
        if (vo.getCashPayment() != null) {
            vo.setCashPayment(vo.getCashPayment().setScale(2, RoundingMode.HALF_UP));
        }
        vo.setPayYearMonth(vo.getPayNy());
    }

    public void combo(List<MiPayVO> voList) {
        for(MiPayVO vo:voList ){
            combo(XssUtils.replaceUnXss(vo));
        }
    }
    public Integer deleteById(Long id){
        return mapper.deleteByPrimaryKey(id);
    }
    public Integer deleteByPayLogId(Long payLogId){
        if(payLogId==0 || payLogId==null){
            return 0;
        }
	    return miPayMapper.deleteByPayLogId(payLogId);
    }
    public Integer createByPayLog(MiPayLogDTO payLog, List<MiPayDTO> dtoList){
        Integer count=0;
        MiPayPO po;
	    for(MiPayDTO dto:dtoList){
            dto=XssUtils.replaceXss(dto);

	        dto.setTargetOrgId(payLog.getTargetOrgId());
	        dto.setPayLogId(payLog.getId());
	        dto.setAid(this.getAID());
            dto.setOptType("1");
            dto.setOptTime(new Date());
            dto.setOptUserId(payLog.getOptUserId());
            po=new MiPayPO();
            po.setPfmId(payLog.getPfmId());
            BeanUtils.copyProperties(dto,po);
            try {
                count+=this.save(po);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        return count;
    }

//    public List<MiPayVO> findByPfmIdAndOrgNo(Long pfmId, String orgNo) {
//        return miPayMapper.findByPfmIdAndOrgNo(pfmId, orgNo);
//    }

    public PageInfo<MiPayVO> getFs(MiPaySDTO sdto, PageSDTO pageSdto) {
        if(pageSdto!=null){
            PageHelper.startPage(pageSdto.getPageNum(), pageSdto.getPageSize());
        }
        List<MiPayVO> voList = miPayMapper.getFs(sdto);
        PageInfo<MiPayVO> page = new PageInfo(voList);
        return page;
    }

    public List<MiPayVO> getFs(MiPaySDTO sdto) {
        return miPayMapper.getFs(sdto);
    }

    /**
     * 生成医保结算信息表-excel
     * @param accountVO
     * @param voList
     * @param fileName
     * @throws Exception
     */
    public void buildDetailFile(MiAccountVO accountVO, List<MiPayVO> voList, String fileName, Date queryTime) throws Exception {
        String templatePath = PAY_EXCEL_TEMLLATE_PATH + File.separator +"payDetail.xlsx";
        ClassPathResource classPathResource = new ClassPathResource(URLDecoder.decode(templatePath, "UTF-8"));
        InputStream inputStream = classPathResource.getInputStream();
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(inputStream), -1);
        CellStyle cellStyle = sxssfWorkbook.createCellStyle();
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);

        CellStyle cellStyleRight = sxssfWorkbook.createCellStyle();
        cellStyleRight.setAlignment(HorizontalAlignment.RIGHT);

        XSSFWorkbook workbook = sxssfWorkbook.getXSSFWorkbook();
        XSSFSheet sheetAt = workbook.getSheetAt(0);
        XSSFRow row1 = sheetAt.getRow(1);
        if (row1 == null) {
            row1 = sheetAt.createRow(1);
        }
        XSSFCell cell111 = row1.getCell(0);
        cell111.setCellStyle(cellStyleRight);
        cell111.setCellValue("查询时间：" + DateUtil.Date2String(queryTime,DateUtil.DEFAULT_TIME_FMT5,null));

        XSSFRow row4 = sheetAt.getRow(4);
        if (row4 == null) {
            row4 = sheetAt.createRow(4);
        }
        XSSFCell cell41 = row4.getCell(1);
        cell41.setCellStyle(cellStyle);
        cell41.setCellValue(accountVO.getOrgName());

        XSSFCell cell42 = row4.getCell(2);
        cell42.setCellStyle(cellStyle);
        cell42.setCellValue(accountVO.getOrgNo());

        XSSFCell cell43 = row4.getCell(3);
        cell43.setCellStyle(cellStyle);
        cell43.setCellValue(accountVO.getAccountBank());

        XSSFCell cell44 = row4.getCell(4);
        cell44.setCellStyle(cellStyle);
        cell44.setCellValue(accountVO.getAccountNo());
        int rowNum = 7;
        int num = 1;
        if (!voList.isEmpty()) {
            for (MiPayVO miPayVO : voList) {
                XSSFRow rowDetail = sheetAt.getRow(rowNum);
                if (rowDetail == null) {
                    rowDetail = sheetAt.createRow(rowNum);
                }
                XSSFCell cell0 = rowDetail.createCell(0);
                cell0.setCellStyle(cellStyle);
                cell0.setCellValue(num);

                XSSFCell cell1 = rowDetail.createCell(1);
                cell1.setCellStyle(cellStyle);
                cell1.setCellValue(StringUtils.isNotBlank(miPayVO.getPayMc()) ? miPayVO.getPayMc() : ""); //医疗机构名称

                XSSFCell cell2 = rowDetail.createCell(2);
                cell2.setCellStyle(cellStyle);
                cell2.setCellValue(StringUtils.isNotBlank(miPayVO.getPayIdno()) ? miPayVO.getPayIdno() : ""); //医疗机构代码

                XSSFCell cell3 = rowDetail.createCell(3);
                cell3.setCellStyle(cellStyle);
                cell3.setCellValue(DateUtil.parseDateToStrByYYYYMMDD(miPayVO.getPayStartDate())); //结算起始日期

                XSSFCell cell4 = rowDetail.createCell(4);
                cell4.setCellStyle(cellStyle);
                cell4.setCellValue(DateUtil.parseDateToStrByYYYYMMDD(miPayVO.getPayeEndDate())); //结算终止日期

                XSSFCell cell5 = rowDetail.createCell(5);
                cell5.setCellStyle(cellStyle);
                cell5.setCellValue(miPayVO.getPersonTimes() != null ? String.valueOf(miPayVO.getPersonTimes()) : ""); //申报人次

                XSSFCell cell6 = rowDetail.createCell(6);
                cell6.setCellStyle(cellStyle);
                cell6.setCellValue(miPayVO.getApplyAmount() != null ? String.valueOf(miPayVO.getApplyAmount().setScale(2, RoundingMode.HALF_UP)) : ""); //申报金额

                XSSFCell cell7 = rowDetail.createCell(7);
                cell7.setCellStyle(cellStyle);
                cell7.setCellValue(miPayVO.getTotalAmount() != null ? String.valueOf(miPayVO.getTotalAmount().setScale(2, RoundingMode.HALF_UP)) : ""); //医疗总费用

                XSSFCell cell8 = rowDetail.createCell(8);
                cell8.setCellStyle(cellStyle);
                cell8.setCellValue(miPayVO.getFundPayment() != null ? String.valueOf(miPayVO.getFundPayment().setScale(2, RoundingMode.HALF_UP)) : ""); //基金支付合计

                XSSFCell cell9 = rowDetail.createCell(9);
                cell9.setCellStyle(cellStyle);
                cell9.setCellValue(miPayVO.getAccountPayment() != null ? String.valueOf(miPayVO.getAccountPayment().setScale(2, RoundingMode.HALF_UP)) : ""); //账户支付合计

                XSSFCell cell10 = rowDetail.createCell(10);
                cell10.setCellStyle(cellStyle);
                cell10.setCellValue(miPayVO.getCashPayment() != null ? String.valueOf(miPayVO.getCashPayment().setScale(2, RoundingMode.HALF_UP)) : ""); //现金支付合计

                XSSFCell cell11 = rowDetail.createCell(11);
                cell11.setCellStyle(cellStyle);
                cell11.setCellValue("1".equals(miPayVO.getPaymentNature()) ? "按月拨付金额" : ""); //款项性质

                XSSFCell cell12 = rowDetail.createCell(12);
                cell12.setCellStyle(cellStyle);
                cell12.setCellValue(StringUtils.isNotBlank(miPayVO.getPayApplyFlowno()) ? miPayVO.getPayApplyFlowno() : ""); //凭证编号

//                XSSFCell cell13 = rowDetail.createCell(13);
//                cell13.setCellStyle(cellStyle);
//                cell13.setCellValue(miPayVO.getQueryReason()); //查询原因

                rowNum++;
                num++;
            }
        }
        FileUtil.createDirectory(payExcelPath);
        //生成文件到本地
        try(FileOutputStream fileOutputStream = new FileOutputStream(Paths.get(payExcelPath + fileName).toFile())) {
            sxssfWorkbook.write(fileOutputStream);
        } catch (IOException e) {
            log.error("生成excel异常，{}", e);
        }finally {
            if (workbook != null) {
                workbook.close();
            }
            if (sxssfWorkbook != null) {
                sxssfWorkbook.dispose();
                sxssfWorkbook.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    /**
     * 响应流从本地读取文件返回
     * @param response
     * @param fileName
     * @param deleteFile
     * @throws Exception
     */
    public void responseDetailFile(HttpServletResponse response, String fileName, boolean deleteFile) throws Exception {
        //响应流从本地读取文件返回
        // 设置响应头
        setResponseHeaders(response, fileName);
        Path filePath = Paths.get(payExcelPath + fileName);
        BufferedInputStream bis = null;
        OutputStream os = null;
        try (InputStream fis = Files.newInputStream(filePath)) {
            bis = new BufferedInputStream(fis);
            os = response.getOutputStream();
            // 3. 使用缓冲区高效传输（8KB缓冲区）
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush();
            if (deleteFile) {
                Files.deleteIfExists(filePath);
            }
        } catch (NoSuchFileException e) {
            // 4. 处理文件不存在异常
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            logger.error("生成文件异常,{}", e);
        } catch (IOException e) {
            // 处理其他IO异常
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            logger.error("生成文件异常,{}", e);
        }finally {
            if (bis != null) {
                bis.close();
            }
            if (os != null) {
                os.close();
            }
        }
    }

    // 5. 设置HTTP响应头
    private void setResponseHeaders(HttpServletResponse response, String fileName) throws Exception {
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
                .replaceAll("\\+", "%20");

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
    }

    public MiPayLogVO findPayLogByQueryOrgIdAndTargetOrgIdAndPfmId(MiPaySDTO sdto) {
        return miPayMapper.findPayLogByQueryOrgIdAndTargetOrgIdAndPfmId(sdto);
    }

    public void buildPlDetailFile(List<MiPayVO> payVoList, String templatePath, String fileName, HttpServletResponse response) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource(URLDecoder.decode(templatePath, "UTF-8"));
        InputStream inputStream = classPathResource.getInputStream();
        Workbook workbook = new HSSFWorkbook(inputStream);
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);

//        CellStyle cellStyleRight = workbook.createCellStyle();
//        cellStyleRight.setAlignment(HorizontalAlignment.RIGHT);
        // 设置水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);

        // 设置垂直居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Sheet sheetAt = workbook.getSheetAt(0);
        int rowNum = 2;
        int num = 1;
        if(!payVoList.isEmpty()) {
            for (MiPayVO miPayVO : payVoList) {
                Row rowDetail = sheetAt.getRow(rowNum);
                if (rowDetail == null) {
                    rowDetail = sheetAt.createRow(rowNum);
                }
                Cell cell0 = rowDetail.createCell(0);
                cell0.setCellStyle(cellStyle);
                cell0.setCellValue(num);

                Cell cell1 = rowDetail.createCell(1);
                cell1.setCellStyle(cellStyle);
                cell1.setCellValue(StringUtils.isNotBlank(miPayVO.getPayMc()) ? miPayVO.getPayMc() : ""); //医疗机构名称

                Cell cell2 = rowDetail.createCell(2);
                cell2.setCellStyle(cellStyle);
                cell2.setCellValue(StringUtils.isNotBlank(miPayVO.getPayIdno()) ? miPayVO.getPayIdno() : ""); //医疗机构代码

                Cell cell3 = rowDetail.createCell(3);
                cell3.setCellStyle(cellStyle);
                cell3.setCellValue(miPayVO.getPayNy()); //结算日期

                Cell cell4 = rowDetail.createCell(4);
                cell4.setCellStyle(cellStyle);
                cell4.setCellValue(miPayVO.getPayRc()); //结算人次

                Cell cell5 = rowDetail.createCell(5);
                cell5.setCellStyle(cellStyle);
                cell5.setCellValue(StringUtils.isNotBlank(miPayVO.getPayYllb()) ? (StringUtils.isNotBlank(McpConst.YLLB.getVal(miPayVO.getPayYllb())) ? McpConst.YLLB.getVal(miPayVO.getPayYllb()) : miPayVO.getPayYllb()) : ""); //医疗类别

                Cell cell6 = rowDetail.createCell(6);
                cell6.setCellStyle(cellStyle);
                cell6.setCellValue(StringUtils.isNotBlank(miPayVO.getPayXzlx()) ? (StringUtils.isNotBlank(McpConst.XZLX.getVal(miPayVO.getPayXzlx())) ? McpConst.XZLX.getVal(miPayVO.getPayXzlx()) : miPayVO.getPayXzlx()) : ""); //险种

                Cell cell7 = rowDetail.createCell(7);
                cell7.setCellStyle(cellStyle);
                cell7.setCellValue(miPayVO.getPayTotalfee() != null ? String.valueOf(miPayVO.getPayTotalfee().setScale(2, RoundingMode.HALF_UP)) : ""); //总费用

                Cell cell8 = rowDetail.createCell(8);
                cell8.setCellStyle(cellStyle);
                cell8.setCellValue(miPayVO.getPayGrzf() != null ? String.valueOf(miPayVO.getPayGrzf().setScale(2, RoundingMode.HALF_UP)) : ""); //个人现金

                Cell cell9 = rowDetail.createCell(9);
                cell9.setCellStyle(cellStyle);
                cell9.setCellValue(miPayVO.getPayJjzf() != null ? String.valueOf(miPayVO.getPayJjzf().setScale(2, RoundingMode.HALF_UP)) : ""); //基金支付

                rowNum++;
                num++;
            }
        }
// 设置响应内容类型
        response.setContentType("application/vnd.ms-excel");

        // 设置响应头，指定下载文件名（处理中文文件名）
        String encodedFilename = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFilename + "\"");
        try{
            // 将工作簿写入响应输出流
            workbook.write(response.getOutputStream());
            // 刷新输出流
            response.flushBuffer();
        }catch (Exception e){
            // 处理其他IO异常
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            logger.error("生成文件异常,{}", e);
        }finally {
            if (workbook != null) {
                workbook.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }


//        BufferedInputStream bis = null;
//        OutputStream os = null;
//        try{
//            bis = new BufferedInputStream(inputStream);
//            os = response.getOutputStream();
//            // 3. 使用缓冲区高效传输（8KB缓冲区）
//            byte[] buffer = new byte[8192];
//            int bytesRead;
//            while ((bytesRead = bis.read(buffer)) != -1) {
//                os.write(buffer, 0, bytesRead);
//            }
//            os.flush();
//        }catch (Exception e){
//            // 4. 处理文件不存在异常
//            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
//            logger.error("生成文件异常,{}", e);
//        }finally {
//            if (inputStream != null) {
//                inputStream.close();
//            }
//            if (bis != null) {
//                bis.close();
//            }
//            if (os != null) {
//                os.close();
//            }
//        }
    }
}
